﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace OS_pre
{
    public partial class Form1 : Form
    {
        class ThreadInfo
        {
            public Thread Thread;
            public int flag = 0;

            public ThreadInfo(Thread thread)
            {
                Thread = thread;
            }
        }

        // 核心代码全局变量
        private delegate void SafeCall(string text);

        private delegate void SafeChangeColor(int[] flag);

        // 统计数据
        private DateTime StartTime;
        private DateTime EndTime;
        private int ProcessNumOfA;
        private int ProcessNumOfB;
        private string InitThreadInfo;

        private static int BUFFERA_SIZE;
        private static int BUFFERB_SIZE;
        private static int INIT_BUFFERA_NUM;
        private static int INIT_BUFFERB_NUM;
        private static int NUM_OF_A; // A类线程数量 从bufferA中取放入bufferB中
        private static int NUM_OF_B; // B类线程数量 从bufferB中取放入bufferA中
        private static int V_OF_A; // A类线程处理速度
        private static int V_OF_B; // B类线程处理速度

        // BUFFER AB中有多少数据
        private Semaphore SemaphoreBufferA;

        private Semaphore SemaphoreBufferB;

        // BUFFER AB中有多少空位
        private Semaphore SemaphoreBufferAEmpty;
        private Semaphore SemaphoreBufferBEmpty;
        private Mutex MutexA = new Mutex();
        private Mutex MutexB = new Mutex();

        private List<ThreadInfo> threadList = new List<ThreadInfo>();

        public static Random _random = new Random();
        private string path;
        private string result = "";
        private bool running = true;
        private FakeBuffer bufferA;
        private FakeBuffer bufferB;

        List<Label> atob = new List<Label>();
        List<Label> btoa = new List<Label>();

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            this.WindowState = FormWindowState.Maximized;
            label5.AutoSize = true;
            label5.Text = "当前版本1.5.0,作者李旭晖戴昊\n" +
                          "操作说明:\n" +
                          "1.点击设置参数，进行初始化参数设置。\n" +
                          "2.设置参数之后点击运行进行模拟。\n" +
                          "4.点击获取结果，结束运行并获取此次结果，生成文件，可供查阅。\n" +
                          "5.结束之后可以多次重新设置。\n" +
                          "6.如有问题请联系邮箱：1664396323@qq.com";
            label1.AutoSize = true;
            label2.AutoSize = true;
            label1.Text = "当前BUFFERA暂未设置参数，请点击参数设置";
            label2.Text = "当前BUFFERB暂未设置参数，请点击参数设置";

            button1.Visible = false;
            Pausebtn.Enabled = false;
            Run.Enabled = false;
            Export.Enabled = false;
        }

        // 核心代码开始
        private void moveA2B(FakeBuffer bufferA, FakeBuffer bufferB)
        {
            while (running)
            {
                // 取数据
                SemaphoreBufferA.WaitOne();
                MutexA.WaitOne();
                work(200, Thread.CurrentThread.Name.Substring(7), "A");
                bufferA.Take();
                MutexA.ReleaseMutex();
                SemaphoreBufferAEmpty.Release();
                // 处理数据
                work(V_OF_A, Thread.CurrentThread.Name.Substring(7), "A");
                object newItem = GetRandomItem();
                ProcessNumOfA++;
                // 放数据
                SemaphoreBufferBEmpty.WaitOne();
                MutexB.WaitOne();
                work(200, Thread.CurrentThread.Name.Substring(7), "A");
                bufferB.Add(newItem);
                MutexB.ReleaseMutex();
                SemaphoreBufferB.Release();
                // UI处理
                SetText(bufferA.GetQueueItem(), bufferB.GetQueueItem());
                result += "从A中取得了" + ",处理之后生成" + newItem + ",放入了BufferB中\n";
            }
        }

        private void moveB2A(FakeBuffer bufferB, FakeBuffer bufferA)
        {
            while (running)
            {
                // 取数据
                SemaphoreBufferB.WaitOne();
                MutexB.WaitOne();
                work(200, Thread.CurrentThread.Name.Substring(7), "B");
                bufferB.Take();
                MutexB.ReleaseMutex();
                SemaphoreBufferBEmpty.Release();
                // 处理数据
                work(V_OF_B, Thread.CurrentThread.Name.Substring(7), "B");
                object newItem = GetRandomItem();
                ProcessNumOfB++;
                // 放数据
                SemaphoreBufferAEmpty.WaitOne();
                MutexA.WaitOne();
                work(200, Thread.CurrentThread.Name.Substring(7), "B");
                bufferA.Add(newItem);
                MutexA.ReleaseMutex();
                SemaphoreBufferA.Release();
                // UI操作
                SetText(bufferA.GetQueueItem(), bufferB.GetQueueItem());
                result += "从B中取得了" + ",处理之后生成" + newItem + ",放入了BufferA中\n";
            }
        }

        /**
         * 处理数据 延时操作
         */
        private void work(int millisecondsTimeout, string index, string type)
        {
            int idx = int.Parse(index);
            ThreadInfo threadInfo;
            if (type == "A")
            {
                threadInfo = threadList[idx - 1];
            }
            else
            {
                threadInfo = threadList[idx - 1 + NUM_OF_A];
            }

            threadInfo.flag = 1;
            Thread.Sleep(millisecondsTimeout);
            threadInfo.flag = 0;
        }

        /**
         * 生产一个新数据
         */
        private Object GetRandomItem()
        {
            char[] content =
            {
                '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                'a', 'b', 'c', 'd', 'e', 'f', 'g',
                'h', 'i', 'j', 'k', 'l', 'm', 'n',
                'o', 'p', 'q', 'r', 's', 't',
                'u', 'v', 'w', 'x', 'y', 'z',
                '[', ']', ';', '@', '#', '$', '%', '^', '&', '*', '(', ')'
            };
            return content[_random.Next(48)];
        }

        /**
         * 向label 1 2中写数据 不能操作UI  开始
         */
        private void SetText(string text, string index)
        {
            WriteText1(text);
            WriteText2(index);
        }

        private void WriteText1(string text)
        {
            if (label1.InvokeRequired)
            {
                var d = new SafeCall(WriteText1);
                label1.Invoke(d, new object[] {text});
            }
            else
            {
                label1.Text = text;
            }
        }

        private void WriteText2(string text)
        {
            if (label2.InvokeRequired)
            {
                var d = new SafeCall(WriteText2);
                label2.Invoke(d, new object[] {text});
            }
            else
            {
                label2.Text = text;
            }
        }
        /* 结束*/

        /**
         * 绘制阻塞运行线程色块
         */
        private void ChangeColor(int[] flag)
        {
            for (int i = 0; i < NUM_OF_A; i++)
            {
                if (atob[i].InvokeRequired)
                {
                    var d = new SafeChangeColor(ChangeColor);
                    atob[i].Invoke(d, new object[] {flag});
                }
                else
                {
                    atob[i].BackColor = flag[i] == 1 ? Color.Green : Color.Red;
                }
            }

            for (int i = 0; i < NUM_OF_B; i++)
            {
                if (btoa[i].InvokeRequired)
                {
                    var d = new SafeChangeColor(ChangeColor);
                    btoa[i].Invoke(d, new object[] {flag});
                }
                else
                {
                    btoa[i].BackColor = flag[i + NUM_OF_A] == 1 ? Color.Green : Color.Red;
                }
            }
        }

        private void PrintBlockThread()
        {
            while (running)
            {
                int[] flag = new int[threadList.Count];
                for (int i = 0; i < threadList.Count; i++)
                {
                    flag[i] = threadList[i].flag;
                }

                ChangeColor(flag);
            }
        }
        /* 结束*/

        private void WriteResult(string content)
        {
            FileStream fs = new FileStream(path,
                FileMode.Append,
                FileAccess.Write);
            StreamWriter sw = new StreamWriter(fs);
            sw.WriteLine(content);
            sw.Flush();
            sw.Close();
            fs.Close();
        }

        // 核心代码结束

        /**
         * 参数设置
         */
        private void Settingbtn_Click(object sender, EventArgs e)
        {
            ParameterSetting setting = new ParameterSetting();
            setting.ShowDialog();
            // A B类线程数量
            NUM_OF_A = setting.producer_num;
            NUM_OF_B = setting.consumer_num;
            // A B类线程处理速度
            V_OF_A = setting.produce_time;
            V_OF_B = setting.consume_time;
            // buffer初始容量和初始化数据容量
            int maxv = setting.buffer_v;
            BUFFERA_SIZE = maxv;
            BUFFERB_SIZE = maxv;
            INIT_BUFFERA_NUM = maxv / 2 + (maxv & 1);
            INIT_BUFFERB_NUM = maxv / 2 + (maxv & 1);

            // AB类UI start
            for (int i = 1; i <= setting.producer_num; ++i)
            {
                Label label = new Label();
                label.AutoSize = false;
                label.BackColor = Color.FromArgb(64, 224, 205);
                label.Width = this.Width / 15;
                ;
                label.Height = this.Height / 15;
                int interval = this.Height / 10;
                label.Left = 80;
                label.Top = interval * i;
                atob.Add(label);
                this.Controls.Add(label);
            }

            for (int i = 1; i <= setting.consumer_num; ++i)
            {
                Label label = new Label();
                label.AutoSize = false;
                label.BackColor = Color.FromArgb(64, 224, 205);
                label.Width = this.Width / 15;
                ;
                label.Height = this.Height / 15;
                int interval = this.Height / 10;
                label.Left = 821;
                label.Top = interval * i;
                btoa.Add(label);
                this.Controls.Add(label);
            }
            // AB类UI end

            // 初始化bufferA信号量中有多少数据
            SemaphoreBufferA =
                new Semaphore(INIT_BUFFERA_NUM, BUFFERA_SIZE);
            // 初始化bufferA信号量中有多少空位
            SemaphoreBufferAEmpty =
                new Semaphore(BUFFERA_SIZE - INIT_BUFFERA_NUM, BUFFERA_SIZE);
            // 初始化bufferB信号量中有多少数据
            SemaphoreBufferB =
                new Semaphore(INIT_BUFFERB_NUM, BUFFERB_SIZE);
            // 初始化bufferB信号量中有多少空位
            SemaphoreBufferBEmpty =
                new Semaphore(BUFFERB_SIZE - INIT_BUFFERB_NUM, BUFFERB_SIZE);

            bufferA = new FakeBuffer(BUFFERA_SIZE, INIT_BUFFERA_NUM);
            bufferB = new FakeBuffer(BUFFERB_SIZE, INIT_BUFFERB_NUM);
            label1.AutoSize = true;
            label2.AutoSize = true;
            label1.Text = bufferA.GetQueueItem() + "\n";
            label2.Text = bufferB.GetQueueItem() + "\n";
            // Pausebtn.Enabled = true;
            Run.Enabled = true;
            // Export.Enabled = true;
            Settingbtn.Enabled = false;
            return;
        }

        /**
         * 运行按钮
         */
        private void Run_Click(object sender, EventArgs e)
        {
            StartTime = DateTime.Now;
            path = DateTime.Now.ToString("yyyyMMddhhmmssfff") + ".txt";
            running = true;
            WriteResult("bufferA初始化大小：" + BUFFERA_SIZE + " ,bufferB初始化大小：" + BUFFERB_SIZE + "\n" +
                        "A类线程数量：" + NUM_OF_A + "个,B类线程数量：" + NUM_OF_B + "个\n" +
                        "A类线程处理时间：" + V_OF_A + "ms ,B类线程处理时间：" + V_OF_B + "ms\n" +
                        "bufferA中初始化数据：" + bufferA.GetQueueItem() + "\n" +
                        "bufferA中初始化数据：" + bufferB.GetQueueItem() + "\n");
            for (int i = 0; i < NUM_OF_A; i++)
            {
                Thread ta = new Thread(() => moveA2B(bufferA, bufferB));
                ta.Name = String.Format("ThreadA{0}", i + 1);
                threadList.Add(new ThreadInfo(ta));
            }

            for (int i = 0; i < NUM_OF_B; i++)
            {
                Thread tb = new Thread(() => moveB2A(bufferB, bufferA));
                tb.Name = String.Format("ThreadB{0}", i + 1);
                threadList.Add(new ThreadInfo(tb));
            }

            Thread print = new Thread(PrintBlockThread);
            print.Start();
            Thread.Sleep(1000);
            foreach (var threadInfo in threadList)
            {
                threadInfo.Thread.Start();
            }

            Run.Enabled = false;
            Pausebtn.Enabled = true;
            Export.Enabled = true;
        }

        /**
         * 暂停按钮
         */
        private void Pausebtn_Click(object sender, EventArgs e)
        {
            if (Pausebtn.Text == "暂停")
            {
                foreach (var threadInfo in threadList)
                {
                    threadInfo.Thread.Suspend();
                }

                Pausebtn.Text = "继续";
            }
            else
            {
                foreach (var threadInfo in threadList)
                {
                    threadInfo.Thread.Resume();
                }

                Pausebtn.Text = "暂停";
            }
        }

        /**
         * 结束以及获取结果
         */
        private void Export_Click(object sender, EventArgs e)
        {
            EndTime = DateTime.Now;
            // 处理总时间
            double totalSeconds = EndTime.Subtract(StartTime).TotalSeconds;
            string finalResult = "总运行时间为：" + totalSeconds + "秒\n" +
                                 "A类线程处理的数据为：" + ProcessNumOfA + "个，B类线程处理的数据为" + ProcessNumOfB + "个\n" +
                                 result;
            // 初始化的参数
            running = false;
            Thread.Sleep(5000);
            WriteResult(finalResult);
            MessageBox.Show("存储完毕");
            button1.Visible = true;
            Pausebtn.Enabled = false;
            Run.Enabled = false;
            Export.Enabled = false;
            Settingbtn.Enabled = true;
            // 重置条件
            threadList.Clear();
            result = "";
            foreach (var t in atob)
            {
                Controls.Remove(t);
            }

            foreach (var t in btoa)
            {
                Controls.Remove(t);
            }

            atob.Clear();
            btoa.Clear();
            label1.AutoSize = true;
            label2.AutoSize = true;
            label1.Text = "当前BUFFERA暂未设置参数，请点击参数设置";
            label2.Text = "当前BUFFERB暂未设置参数，请点击参数设置";
        }

        private void button1_Click(object sender, EventArgs e)
        {
            StreamReader hc = new StreamReader(path);
            string ss = hc.ReadToEnd();
            Result result = new Result(ss);
            result.ShowDialog();
        }
    }
}